package xjf.learn.stream;

import org.junit.Test;
import xjf.base.constant.STATUS;
import xjf.base.entity.Employee;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * 1. Stream 的执行顺序
 *
 * 总结：stream API只能尽可能减少迭代次数，并不是说一次结束操作只会触发一次迭代。
 *      对于有状态的中间操作，比如distinct()、sorted()，只有对元素一次完整迭代之后才能确定结果，
 *      其后的其他操作会有新的迭代。
 * @Author: xjf
 * @Date: 2020/4/13 0:08
 */
public class Test6 {

    /**
     * 数据准备
     */
    private List<Employee> employeeList = Arrays.asList(
            new Employee("张三", 45, 6000, STATUS.BUSY),
            new Employee("李四", 20, 7600, STATUS.FREE),
            new Employee("王五", 38, 4900, STATUS.VACATION),
            new Employee("赵六", 77, 2000, STATUS.BUSY),
            new Employee("田七", 54, 6500, STATUS.FREE),
            new Employee("田七", 54, 6500, STATUS.FREE)
    );

    /**
     * 1. 迭代一次：在一次流的执行中，会执行一次将所有可能运行操作都执行
     */
    @Test
    public void test1(){
        // map 和 filter 会执行 5 次，foreach 执行 1 次
        Stream.of("d2", "a2", "b1", "b3", "c")
                .map(s -> {
                    System.out.println("map: " + s);
                    return s.toUpperCase();
                })
                .filter(s -> {
                    System.out.println("filter: " + s);
                    return s.startsWith("A");
                })
                .forEach(s -> System.out.println("forEach: " + s));
    }

    /**
     * 对上一个 test 中的顺序执行调换
     */
    @Test
    public void test2(){
        // filter 执行 5 次， map 和 foreach 都执行 1 次
        Stream.of("d2", "a2", "b1", "b3", "c")
                .filter(s -> {
                    System.out.println("filter: " + s);
                    return s.startsWith("a");
                })
                .map(s -> {
                    System.out.println("map: " + s);
                    return s.toUpperCase();
                })
                .forEach(s -> System.out.println("forEach: " + s));
    }

    /**
     * 2. 有状态的中间操作会执行一次迭代
     */
    @Test
    public void test3(){
        // sort 会执行一次全迭代
        Stream.of("d2", "a2", "b1", "b3", "c")
                .sorted((s1, s2) -> {
                    System.out.printf("sort: %s; %s\n", s1, s2);
                    return s1.compareTo(s2);
                })
                .filter(s -> {
                    System.out.println("filter: " + s);
                    return s.startsWith("a");
                })
                .map(s -> {
                    System.out.println("map: " + s);
                    return s.toUpperCase();
                })
                .forEach(s -> System.out.println("forEach: " + s));
    }

    /**
     * 对上一个操作进行优化
     */
    @Test
    public void test4(){
        // 此时 filter 不会被调用，因为 filter 后只有一个元素，不会再进行排序
        Stream.of("d2", "a2", "b1", "b3", "c")
                .filter(s -> {
                    System.out.println("filter: " + s);
                    return s.startsWith("a");
                })
                .sorted((s1, s2) -> {
                    System.out.printf("sort: %s; %s\n", s1, s2);
                    return s1.compareTo(s2);
                })
                .map(s -> {
                    System.out.println("map: " + s);
                    return s.toUpperCase();
                })
                .forEach(s -> System.out.println("forEach: " + s));
    }
}
